#define KEY_STATE_0           0
#define KEY_STATE_1           1
#define KEY_STATE_2           2
#define KEY_STATE_3           3
 
#define KEY_NONE 		      0
#define KEY_CLICK	          1
#define KEY_DOUBLE	          2
#define KEY_LONG	          3

#define CNT_LONG	          100
#define CNT_DOUBLE	          50
 
#define KEY_INPUT	//gpio读取
/***************************************************************************
程序功能：一个按键的单击、双击、长按。三种按键方式，然后做不同的处理。   
***************************************************************************/
 
static uint8_t key_driver(void)
{
	static uint8_t state_level_0 = KEY_STATE_0;
	static uint8_t key_timer_cnt1 = 0;
	uint8_t key_state = KEY_NONE;
	uint8_t current_state;
	
	current_state = KEY_INPUT;  //read the I/O states
	
	switch(state_level_0)
	{
		case KEY_STATE_0:
			if(current_state == 0)
				state_level_0 = KEY_STATE_1; 
				//按键被按下，状态转换到按键消抖和确认状态//
			break;
			
		case KEY_STATE_1:
			if(current_state == 0)
			{
				key_timer_cnt1 = 0;
				state_level_0 = KEY_STATE_2;
				//按键仍然处于按下状态
				//消抖完成，key_timer开始准备计时
				//状态切换到按下时间计时状态
			}
			else
				state_level_0 = KEY_STATE_0;
				//按键已经抬起，回到按键初始状态
			break;  //完成软件消抖
			
		case KEY_STATE_2:
			if(current_state == 1) 
			{
				key_state = KEY_CLICK;  //按键抬起，产生一次click操作
				state_level_0 = KEY_STATE_0;  //转换到按键初始状态
			}
			else if(++key_timer_cnt1 >= CNT_LONG)  //按键继续按下，计时超过1000ms
			{
				key_state = KEY_LONG;  //送回长按事件
				state_level_0 = KEY_STATE_3;  //转换到等待按键释放状态
			}
			break;
			
		case KEY_STATE_3:  //等待按键释放
			if(current_state == 1)  //按键释放
				state_level_0 = KEY_STATE_0;  //切回按键初始状态
			break;
	}
	return key_state;
}
 
/***************************************************************************
函数功能：中层按键处理函数，调用底层函数一次，处理双击事件的判断，
                                        返回上层正确的无键、单击、双击、长按四种状态
本函数由上层循环调用，间隔10ms
***************************************************************************/
uint8_t key_read(void)
{
	static uint8_t state_level_1 = KEY_STATE_0;
	static uint8_t key_timer_cnt2 = 0;
	uint8_t key_level = KEY_NONE;
	uint8_t key;
	
	key = key_driver();
	
	switch(state_level_1)
	{
		case KEY_STATE_0:
			if(key == KEY_CLICK)
			{
				key_timer_cnt2 = 0;  //第一次单击，不返回，到下个状态判断是否会出现双击
				state_level_1 = KEY_STATE_1;
			}
			else 
				key_level = key;  //对于无键、长按，返回原事件
			break;
			
		case KEY_STATE_1:
			if(key == KEY_CLICK)  //又一次单击，时间间隔小于500ms
			{
				key_level = KEY_DOUBLE;  //返回双击事件，回到初始状态
				state_level_1 = KEY_STATE_0;
			}
			else if(++key_timer_cnt2 >= CNT_DOUBLE)
			{
				//这里500ms内肯定读到的都是无键事件，因为长按大于1000ms
				//在1s前底层返回的都是无键
														
				key_level = KEY_CLICK;  //500ms内没有再次出现单击事件，返回单击事件
				state_level_1 = KEY_STATE_0;  //返回初始状态
							
			}
			break;
	}
	
	return key_level;
}